

/*
 * Escenario.java
 *
 * Created on 20 de febrero de 2008, 0:27
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.io.File;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import musica.Cancion;
import musica.Player;

import interfaz.*;
import java.util.ArrayList;

public class Principal extends Canvas implements KeyListener {


    private static String RUTAPROBA = "/Volumes/Saco de Esteban/iTunes";
    private static String RUTAFOTOS = "/Users/esteban/Pictures/Photo Booth";
//    private static String RUTAPROBA = "/Users/esteban/media_center_files"; 


/*  
 * 
 * 
    private static String RUTAPROBA = "/Users/victor/Music/Outros";
    private static String RUTAFOTOS = "/Users/victor/Pictures/Photo Booth";
     * */

    
    public static final int winWIDTH = 1280; //tamanho da venta
    public static final int winHEIGHT = 800;
    private static int refrescoInicial = 100;
    private static boolean fullscreen = true;
    private static GraphicsDevice gd = null; //para pantalla completa
    private static JFrame ventana;
    public BufferStrategy strategy; //buffer de pintura de pantalla
    private static BufferEscenarios escenarios = new BufferEscenarios();
    /*almaceno os escenarios xa creados*/
    private static String escenarioActual; //escenario que se ve actualmente
    private static boolean cargando = false; //estamos cargando un escenario?
    private static int contadorRefrescos = 0;
    private static int refresco;

    public Principal() {
        ventana = new JFrame("Escenario");

        //seria boa idea facer unha subrutina para cargar valores por defecto
        //pantalla completa, dimensions, etc, dun ficheiro de conf.

        addKeyListener(this); //empezamos a escoitar ao teclado
        iniciarVentana(); //algunhas instruccions de inicializacion da venta
        createBufferStrategy(2);
        strategy = getBufferStrategy();
        requestFocus();
    }

    //metodos para a xestion de escenarios
    private static void ajustarEscenarioActual(String clave) {
        escenarioActual = clave;
    }

    private static Escenario obtenerEscenario(String escenario) {
        /*miramos que o escenario indicado estea no buffer. Se non esta,
         *activamos o flag de carga, iniciamos o escenario, e devolvemolo.
         *o timer e para mostrar o escenario de carga */
        if (!escenarios.contieneEscenario(escenario)) {
            cargando = true;
            iniciarEscenario(escenario); /*esta subrutina xa agrega o escenario
             *ao buffer*/
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        cargando = false;
        return ((Escenario) escenarios.obtenerEscenario(escenario));
    }

    //eliminar bordes, sair ao pechar, preparar capa awt
    private void iniciarVentana() {
        ventana.setBounds(0, 0, winWIDTH, winHEIGHT); //damos tamanho
        JPanel panel = (JPanel) ventana.getContentPane(); //creamos mapa de debuxo
        setBounds(0, 0, winWIDTH, winHEIGHT); //damos tamanho ao mapa
        panel.setPreferredSize(new Dimension(winWIDTH, winHEIGHT));
        panel.setLayout(null);
        panel.add(this);
        ventana.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        //exit on close
        ventana.setUndecorated(true); //eliminamos bordes
        org.jdesktop.layout.GroupLayout layout =
                new org.jdesktop.layout.GroupLayout(ventana.getContentPane());
        ventana.getContentPane().setLayout(layout);  //creamos layout
        ventana.pack();
    }

    //inicializacion da capa awt
    public void paint(Graphics g) {
        //A executar na inicializacion do programa
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, winWIDTH, winHEIGHT);
    }

    private static void cargarEscenarioArtistas(String escenario) {
        String[] artistas = new String[2]; /*Invocar a unha especie de
         *artistas = listarArtistas(),
         *e que esteban devolva os
         *artistas da BD */
        String[] caratulas = new String[2]; //o mesmo
        caratulas[0] = "iTunes.png";
        caratulas[1] = "iTunes.png";
        artistas[0] = "Maceo Parker";  /*Informacion de exemplo */
        artistas[1] = "The Bee Gees";

        Escenario coleccion =
                EscenariosDefinidos.ListaIconos(caratulas, artistas, true);
        /*Cargamos unha lista de elementos como escenario, indicamos
         *a lista a seguir, e o segundo parametro indica se son carpetas
         *ou non */
        coleccion.setId(escenario); //Diferencias escenarios entre si
        coleccion.setTitle(EscenariosDefinidos.ARTISTAS);
        escenarios.agregarEscenario(coleccion, escenario); /*Agregar ao
     *buffer */
    }

    private static void cargarEscenarioAlbumes(String escenario) {
        String[] albumes = new String[3]; //esteban ten que darme unha lista
        //agregamos escenario a lista
        albumes[0] = "Greatest Hits";
        albumes[1] = "Made By Maceo";
        albumes[2] = "Mo Roots";

        String[] caratulas = new String[3]; //o mesmo
        caratulas[0] = "iTunes.png";
        caratulas[1] = "iTunes.png";
        caratulas[2] = "iTunes.png";

        Escenario coleccion =
                EscenariosDefinidos.ListaIconos(caratulas, albumes, true);
        coleccion.setId(escenario);
        coleccion.setTitle(EscenariosDefinidos.ALBUMES);
        escenarios.agregarEscenario(coleccion, escenario);
    }

    private static void cargarEscenarioXeneros(String escenario) {
        String[] xeneros = new String[2]; //esteban ten que darme unha lista
        //agregamos escenario a lista
        xeneros[0] = "Funk";
        xeneros[1] = "Disco";
        String[] caratulas = new String[2]; //o mesmo
        caratulas[0] = "iTunes.png";
        caratulas[1] = "iTunes.png";

        Escenario coleccion =
                EscenariosDefinidos.ListaIconos(caratulas, xeneros, true);
        coleccion.setId(escenario);
        coleccion.setTitle(EscenariosDefinidos.XENEROS);
        escenarios.agregarEscenario(coleccion, escenario);
    }

    private static void cargarEscenarioListaCancions(String escenario) {
        List listaCanciones =
                Cancion.buscar_canciones(
                new File(RUTAPROBA));
        String[] listaPath = new String[listaCanciones.size()];
        String[] lista = new String[listaCanciones.size()];
        iTextMenu menu = new iTextMenu(0, 0);
        menu.setWidth(0);

        for (int i = 0; i < listaCanciones.size(); i++) {
            listaPath[i] = ((Cancion) listaCanciones.get(i)).getPath();
            lista[i] = (new File(listaPath[i])).getName();
            menu.addItem(listaPath[i], false);
        }
        Escenario esc =
                EscenariosDefinidos.Lista(lista, false);

        menu.setFont(new Font("Verdana", 0, 0));

        int menuItem = esc.addItem(menu);
        esc.addListening(menuItem);
        esc.setMenuItem(menuItem);

        esc.setTitle(EscenariosDefinidos.LISTA);
        esc.setPrevEsc(EscenariosDefinidos.PRINCIPAL);
        esc.setId(EscenariosDefinidos.LISTA);
        escenarios.agregarEscenario(esc, escenario);
    }

    private static void cargarEscenarioFotos(String escenario) {
        Escenario esc;

        String[] fotos = obtenerFotosEnCarpeta(RUTAFOTOS);
        String[] titulos = new String[fotos.length];

        iTextMenu menu = new iTextMenu(0, 0);
        menu.setWidth(0);

        menu.setFont(new Font("Verdana", 0, 0));

        for (int i = 0; i < titulos.length; i++) {
            titulos[i] = new File(fotos[i]).getName();
            menu.addItem(fotos[i], false);
        }


        /*agregamos escenario ao buffer. False volve indicar se son
         *explorables */
        esc = EscenariosDefinidos.ListaIconos(fotos, titulos, false, 1);

        int menuItem = esc.addItem(menu);
        esc.addListening(menuItem);
        esc.setMenuItem(menuItem);

        esc.setTitle(EscenariosDefinidos.FOTOS);
        esc.setPrevEsc(EscenariosDefinidos.PRINCIPAL);
        esc.setId(EscenariosDefinidos.FOTOS);
        escenarios.agregarEscenario(esc, escenario);
    }

    private static void escenarioReproducirMusica(String escenario) {
                            //Escenario de reproduccion
        String titulo, album, autor, caratula;

        /*OLLO!! hai que incrementar en 1 o indice "loxico" porque
         *aparece a etiqueta Reproducir
         *Reproducir=Artistas=Maceo Parker=Artistas en nivel 1*/
        autor = RutaEscenario.obtenerNivel(escenario,
                RutaEscenario.numeroNiveles(escenario) - 2);
        album = RutaEscenario.obtenerNivel(escenario,
                RutaEscenario.numeroNiveles(escenario) - 1);
        titulo = RutaEscenario.obtenerNivel(
                escenario, RutaEscenario.numeroNiveles(escenario));
        caratula = "iTunes.png";

        Escenario coleccion;

        coleccion =
                EscenariosDefinidos.ReproduccionMusica(
                autor, album, titulo, caratula);

        coleccion.setId(escenario); /*Interesa que os escenarios de
         *reproduccion sexan diferenciables
         *entre si, xa que temos que cambiar
         *os valores dos items, e e a unica
         *forma */
        coleccion.setNextEsc(escenario); /*Se pulsamos enter, o
         *escenario deberia seguir
         *sendo o mesmo */
        coleccion.setPrevEsc(
                escenario.substring(escenario.indexOf("=") + 1,
                escenario.lastIndexOf("=")));
        /*O escenario anterior deberia ser o que
         *invocou ao escenario de reproduccion*/

        escenarios.agregarEscenario(coleccion, escenario);
    }
    
    private static void escenarioReproducirMusicaDendeLista(String escenario) {
        (new Player()).play(
                RutaEscenario.obtenerUltimoNivel(escenario));

        String autor, album, titulo, caratula;
        autor = "";
        album = "";
        titulo = (new File(RutaEscenario.obtenerUltimoNivel(escenario)))
                .getName();
        caratula = "iTunes.png";

        Escenario coleccion;

        coleccion =
                EscenariosDefinidos.ReproduccionMusica(
                autor, album, titulo, caratula);

        coleccion.setId(escenario); /*Interesa que os escenarios de
         *reproduccion sexan diferenciables
         *entre si, xa que temos que cambiar
         *os valores dos items, e e a unica
         *forma */
        coleccion.setNextEsc(escenario); /*Se pulsamos enter, o
         *escenario deberia seguir
         *sendo o mesmo */
        coleccion.setPrevEsc(
                escenario.substring(escenario.indexOf("=") + 1,
                escenario.lastIndexOf("=")));          
        /*O escenario anterior deberia ser o que
         *invocou ao escenario de reproduccion*/

        escenarios.agregarEscenario(coleccion, escenario);
    }
    
    private static String[] obtenerFotosEnCarpeta (String path) {
        File[] actual = new File(path).listFiles();
        ArrayList lista = new ArrayList();

        for (int i = 0; i < actual.length; i++) {
            if (actual[i].isFile() && actual[i].getName().endsWith(".jpg")) {
                lista.add(actual[i].getAbsolutePath());
            }
            if (actual[i].isFile() && actual[i].getName().endsWith(".JPG")) {
                lista.add(actual[i].getAbsolutePath());
            }
        }
        
        String[] fotos = new String[lista.size()];
        for (int i = 0; i < fotos.length; i++) {
            fotos[i] = (String) lista.get(i);
        }
        return fotos;
    }
    
    private static void escenarioReproducirFoto(String escenario) {
        Escenario coleccion = EscenariosDefinidos.ReproducirFoto(
                RutaEscenario.obtenerUltimoNivel(escenario));

        
        coleccion.setId(escenario);
        coleccion.setNextEsc(escenario.substring(
                0, escenario.lastIndexOf("=")));

        escenarios.agregarEscenario(coleccion, escenario);
    }
    
    private static void escenarioNavegacionNiveles (String escenario) {
        int numNiveles = RutaEscenario.numeroNiveles(escenario);
        String tipoBusqueda =
                RutaEscenario.obtenerTipoBusqueda(escenario);


        String[] resultados;  /*Esteban debe proporcionar esta
         *informacion */
        resultados = new String[2];
        resultados[0] = tipoBusqueda + " en nivel " + numNiveles;
        resultados[1] = tipoBusqueda + " (2) en nivel " + numNiveles;
        String[] caratulas = new String[2]; //o mesmo
        caratulas[0] = "iTunes.png";
        caratulas[1] = "iTunes.png";

        //resultados = buscarPor(tipoBusqueda,nivel1,nivel2,...);

        /*Por exemplo, no terceiro nivel estan as cancions.
         *Por iso e false a partir de ai. Este valor pode cambiar en
         *funcion do tipo de busqueda. Por exemplo, para artistas hai
         *3 niveis: artista, album, cancion; mentres que para xenero hai
         *4: xenero, artista, album, cancion. */
        Escenario coleccion =
                EscenariosDefinidos.ListaIconos(
                caratulas, resultados, (numNiveles < 3));

        coleccion.setId(escenario); /*Interesa que o menu
        Musica=Artisas=Paco sexa sempre o mesmo, porque non
         *vamos albergar a posibilidade de
         *que apareza nova musica durante
         *a execucion */
        coleccion.setTitle(
                RutaEscenario.obtenerNivel(escenario, numNiveles));
        //O ultimo nivel corresponde ao escenario actual

        escenarios.agregarEscenario(coleccion, escenario);
    }
    
    //creacion dos escenarios
    private static void iniciarEscenario(String escenario) {
        System.out.println(escenario); /*tenhamos unha lixera idea
         *de onde estamos */

        if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.PRINCIPAL)) {
            //Escenario principal
            escenarios.agregarEscenario(
                    EscenariosDefinidos.Principal(), escenario);
        } else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.MUSICA)) {
            //Escenario Musica
            escenarios.agregarEscenario(
                    EscenariosDefinidos.Musica(), escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.ARTISTAS)) {
            //Escenario artistas
            Principal.cargarEscenarioArtistas(escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.ALBUMES)) {
            //Escenario albumes
            Principal.cargarEscenarioAlbumes(escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.XENEROS)) {
            //Escenario xeneros
            Principal.cargarEscenarioXeneros(escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.LISTA)) {
            //Escenario lista cancions
            Principal.cargarEscenarioListaCancions(escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.FOTOS)) {
            //Escenario fotos
            Principal.cargarEscenarioFotos(escenario);
        } 
        else if (RutaEscenario.obtenerUltimoNivel(escenario).
                equalsIgnoreCase(EscenariosDefinidos.QUIT)) {
            //Rutina de saida do programa
            System.exit(0);
        } 
        
        
        //ENTRAMOS EN ESCENARIOS DINAMICOS
        else if (RutaEscenario.numeroNiveles(escenario) > 0) {
            /*Numero de niveis da ruta. Por exemplo, para
            ARTISTAS=Maceo Parker=Mo Roots=Chicken hai 3 niveis. */

            /*TipoBusqueda e a primeira etiqueta da ruta de escenario */
            if (RutaEscenario.obtenerCategoria(escenario).
                    equalsIgnoreCase(EscenariosDefinidos.PLAY)) {
                if (RutaEscenario.obtenerTipoBusqueda(escenario).
                        equalsIgnoreCase(EscenariosDefinidos.MUSICA)) {
                    //Escenario reproducir musica
                    Principal.escenarioReproducirMusica(escenario);

                } else if (RutaEscenario.obtenerTipoBusqueda(escenario).
                        equalsIgnoreCase(EscenariosDefinidos.LISTA)) {
                    //Escenario reproducir musica dende lista
                    Principal.escenarioReproducirMusicaDendeLista(escenario);
                } else if (RutaEscenario.obtenerTipoBusqueda(escenario).
                        equalsIgnoreCase(EscenariosDefinidos.FOTOS)) {
                    //Escenario reproducir fotos
                    Principal.escenarioReproducirFoto(escenario);
                }

            } else {
                /* Subescenarios entre os definidos e os de reproduccion. Por
                 * exemplo albums de maceo parker, lista de temas do album
                 * x... */
                Principal.escenarioNavegacionNiveles(escenario);
            }
        } else /*Todolos posibles casos de escenarios xa os vimos, se non esta
         *albergado, e que esta mal*/ {
            ajustarEscenarioActual(EscenariosDefinidos.PRINCIPAL);
        }
        cargando = false;
    }

    //repintar a pantalla en cada actualizacion
    public void repaint() {
        Graphics g = strategy.getDrawGraphics();

        g.setColor(Color.BLACK);
        g.fillRect(0, 0, winWIDTH, winHEIGHT);

        if (cargando) {
            Escenario carga = EscenariosDefinidos.Cargando();
            carga.setFadeInEffect(false);
            carga.paint(g);
        } else {
            obtenerEscenario(escenarioActual).paint(g);
        }

        strategy.show();
    }

    //algoritmo de actualizacion da capa awt
    private void actualizar() {
        float durmir;
        //actualizar escenarios
        //enviar eventos
        while (isVisible()) {
            durmir = 1000 / refresco;
            try {
                Thread.sleep((long) durmir);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            /* Unha vez chegados a 500 refrescos interesa reducir a frecuencia
            para non consumir recursos inutilmente */
            contadorRefrescos++;
            if (contadorRefrescos >= 500) {
                refresco = 4;
            }
            repaint();
        }
    }

    public static void main(String[] args) {
        ImageBuffer.cargarInterrogante();
        Escenario.setWidth(winWIDTH);
        Escenario.setHeight(winHEIGHT);
        refresco = refrescoInicial;
        contadorRefrescos = 0;
        ajustarEscenarioActual(EscenariosDefinidos.PRINCIPAL);

        Principal inv = new Principal();

        EscenariosDefinidos.setCanvas(inv); /* Necesario un obxecto Canvas para
         *as imaxes */


        //Creamos pantalla completa
        if (fullscreen) {
            GraphicsEnvironment ge =
                    GraphicsEnvironment.getLocalGraphicsEnvironment();

            gd = ge.getDefaultScreenDevice();


            if (!gd.isFullScreenSupported()) {
                System.out.println("WARNING: No hay soporte.\n");
            } else {
                System.out.println("INFO: Detectado soporte\n");
            }


            try {
                gd.setFullScreenWindow(inv.ventana);
            } catch (Throwable e) {
                e.printStackTrace();
                System.out.println("ERROR CRITICO: " + e.getMessage());
                System.exit(0);
            }
        }
        inv.actualizar();

    }

    //Control de teclado
    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        //recobramos un refresco rapido para as animacions
        refresco = refrescoInicial;
        contadorRefrescos = 0;
        switch (e.getKeyCode()) {
            case KeyEvent.VK_ENTER: {
                cargando = true; //necesitamos cargar el escenario
                ajustarEscenarioActual(
                        obtenerEscenario(escenarioActual).getNextEsc());
                break;
            }
            case KeyEvent.VK_ESCAPE: {
                cargando = true;
                ajustarEscenarioActual(
                        obtenerEscenario(escenarioActual).getPrevEsc());
                break;
            }
        }
        //enviamos o evento ao escenario, para que el faga o que considere
        obtenerEscenario(escenarioActual).keyPressed(e);
    }

    public void keyReleased(KeyEvent e) {
    }
}
